/*
 * network.cpp
 *
 *  Created on: 26/06/2011
 *      Author: George Ferreira
 */

#include "network.h"
#include "helper.h"

#include <iostream>

using namespace std;
bool Network::empty(std::vector <Node*> &elements){
	nodes = 0;

	for (unsigned i = 0; i < elements.size(); i++ ){
		elements[i] = (Node*)NULL;
	}

	return true;
}

bool Network::free(std::vector <Node*> &elements){
	for (unsigned i = 0; i < elements.size(); i++ ){
		if ( elements[i] != NULL ){
			delete elements[i];
		}
		elements[i] = (Node*)NULL;
	}

	return true;
}


unsigned Network::hash(Node *host){
	unsigned hashValue = 0;

	const char *pattern = (const char*) &host->ip;

	for (unsigned int i =0; i < sizeof(u_int32_t); i++){
		hashValue = 37*hashValue + pattern[i];
	}

	return hashValue;
}

unsigned Network::position(Node *host){
	unsigned position = hash(host)%elements.size();
	unsigned i = 0;

	while(elements[position] != NULL && elements[position]->ip != host->ip ){
		position += 2*++i - 1;
		if ( position >= elements.size()){
				position -= elements.size();
		}
	}

	return position;
}

unsigned Network::insert(Node *host){
	unsigned pos = position(host);

	if (elements[pos] == NULL ){
		elements[pos] = host;
		if ( ++nodes > elements.size()/2 ){
			heHash();
			pos = position(host);
		}

	}else if ( *elements[pos] == *host){
		throw DuplicatedNodeException();
	}

	if ( pos != position(host) ){
		std::cout << "**WARING " << pos << "==" << position(host) << "***" << std::endl;
	}

	return pos;
}

unsigned Network::heHash(){
	std::vector <Node*> oldElements = elements;
	unsigned newsize = dataStruct::Helper::nextPrime(elements.size()*2);

	elements.resize(newsize);
	empty(elements);

	for(unsigned i=0; i < oldElements.size(); i++){
		if ( oldElements[i] != NULL ){
			insert(oldElements[i]);
		}
	}

	return newsize;
}

Host *Network::find(Node *host){
	unsigned pos = position(host);
	return elements[pos];
}

Network::Network(){
	elements.resize(101);
	nodes = 0;
	empty(elements);
}
